import { Link } from "../../app_base/module/structure/Link";
import { G_Config } from "../../config/ConfigManager";
import { Levels } from "../../config/ConfigStructures";
import { Recover } from "../component/Recover";

type StringOrNumber = string | number;

type LevelStruct = {
    /**
     * 关卡解锁列表
     */
    unlockLevels: StringOrNumber[],
    /**
     * 关卡通关列表
     */
    passLevels: StringOrNumber[],
}

const DefData: LevelStruct = {
    unlockLevels: [],
    passLevels: [],
}

/**
 * 玩家关卡数据
 */
export class LevelLink extends Link<LevelStruct>{
    /**
     * 关卡内倒计时,不存入数据
     */
    private _countdown: Recover;
    constructor() {
        super("level", DefData);
        this.append(LevelAnswer, LevelHint);
    }

    protected _restSelfData(): void {
        this._data.unlockLevels = [G_Config.level.findData<Levels>(0).id];
        this._data.passLevels.length = 0;
    }

    parse(value: string | Object): void {
        super.parse(value);
        console.log('关卡缓存数据实例化', value);

        /** 后加的数据手动添加 */
        let keys = Object.keys(DefData);
        for (let key of keys) {
            if (!(key in this._data)) {
                this._data[key] = DefData[key];
            }
        }
    }

    public get answer(): LevelAnswer {
        return this['answer'];
    }

    public get hint(): LevelHint {
        return this['hint'];
    }

    public get countdown(): Recover {
        if (!this._countdown) {
            this._countdown = new Recover();
        }
        return this._countdown;
    }

    /**
     * 开始关卡内倒计时
     * @param time 倒计时时长
     * @param onUpdated 更新监听函数
     * @param caller 监听者
     */
    public startCountdown(time: number, onUpdated?: (value: number, addValue: number) => void, caller?: any): void {
        onUpdated && this.countdown.onUpdated(onUpdated, caller);
        this.countdown.start(time, Number.MAX_SAFE_INTEGER, 0, 1000, -1);
    }

    /**
     * 关卡解锁列表
     */
    public get unlockLevels(): StringOrNumber[] {
        return this._data.unlockLevels.concat();
    }

    /**
     * 解锁关卡
     * @param level 目标关卡
     */
    public unlockLevel(level: StringOrNumber): void {
        if (!this.isUnlock(level)) {
            this._data.unlockLevels.push(level);
            this.updated("unlockLevels", level, null);
        }
    }

    /**
     * 关卡是否解锁
     * @param level 目标关卡 
     * @returns 
     */
    public isUnlock(level: StringOrNumber): boolean {
        return this._data.unlockLevels.includes(level);
    }

    /**
     * 通关关卡列表
     */
    public get passLevels(): StringOrNumber[] {
        return this._data.passLevels.concat();
    }

    /**
     * 关卡是否通关
     * @param level 目标关卡
     * @returns 
     */
    public isPass(level: StringOrNumber): boolean {
        return this._data.passLevels.includes(level);
    }

    /**
     * 保存通关关卡
     * @param level 目标关卡
     */
    public passLevel(level: StringOrNumber): void {
        if (!this.isPass(level)) {
            this._data.passLevels.push(level);
            this.updated("passLevels", level, null);
        }
    }
}

type LevelAnswerStruct = {
    /**
     * 用户查看关卡答案数据
     */
    answers: StringOrNumber[],
}

/**
 * 玩家查看关卡答案的数据列表
 */
class LevelAnswer extends Link<LevelAnswerStruct> {
    constructor() {
        super("answer", {
            answers: [],
        });
    }

    protected _restSelfData(): void {
        this._data.answers.length = 0;
    }

    /**
     * 已查看答案的关卡列表
     */
    public get answers(): StringOrNumber[] {
        return this._data.answers.concat();
    }

    /**
     * 是否已经查看答案
     * @param level 目标关卡
     * @returns 
     */
    public hasLook(level: StringOrNumber): boolean {
        return this._data.answers.includes(level);
    }

    /**
     * 查看答案后保存数据
     * @param level 目标关卡
     */
    public saveAnswer(level: StringOrNumber): void {
        if (!this.hasLook(level)) {
            this._data.answers.push(level);
            this.updated("answers", level, null);
        }
    }
}


type LevelHintStruct = {
    /**
     * 用户查看关卡提示数据
     */
    hints: StringOrNumber[],
}

/**
 * 玩家查看关卡提示的数据列表
 */
class LevelHint extends Link<LevelHintStruct> {
    constructor() {
        super("hint", {
            hints: [],
        });
    }

    protected _restSelfData(): void {
        this._data.hints.length = 0;
    }

    /**
     * 已查看关卡提示的列表
     */
    public get hints(): StringOrNumber[] {
        return this._data.hints.concat();
    }

    /**
     * 目标关卡是否已经查看提示
     * @param level 目标关卡
     * @returns 
     */
    public hasHint(level: StringOrNumber): boolean {
        return this._data.hints.includes(level);
    }

    /**
     * 查看提示后保存数据
     * @param level 目标关卡
     */
    public saveHint(level: StringOrNumber): void {
        if (!this.hasHint(level)) {
            let oldValue = this.hints;
            this._data.hints.push(level);
            this.updated("hints", this._data.hints, oldValue);
        }
    }
}
